package cn.nlsde.service.impl;

import cn.nlsde.constant.Constants;
import cn.nlsde.dao.CompanyMapper;
import cn.nlsde.dao.EnterpriseEvaluationMapper;
import cn.nlsde.dao.TemplateDetailMapper;
import cn.nlsde.entity.Company;
import cn.nlsde.entity.EnterpriseEvaluation;
import cn.nlsde.entity.Evaluation;
import cn.nlsde.service.ExcelService;
import cn.nlsde.util.NormUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;

/**
 * Created by zwj on 2016/10/20.
 */

@Service
public class ExcelServiceImpl implements ExcelService {

    public final Logger logger = LoggerFactory.getLogger(ExcelServiceImpl.class);

    @Autowired
    CompanyMapper companyMapper;

    @Autowired
    EnterpriseEvaluationMapper enterpriseEvaluationMapper;


    @Autowired
    TemplateDetailMapper templateDetailMapper;

    @Override
    public Pair<Boolean, String> getEvaluation(Integer templateId, byte[] buff, boolean isE2007) {

        Pair<Boolean, String> booleanStringPair = checkExcel(buff, isE2007);

        if (booleanStringPair.getLeft()) {
            EnterpriseEvaluation enterpriseEvaluation = enterpriseEvaluationMapper
                    .selectByTemplateId(templateId);
            List<Company> companies = readExcel(buff, isE2007, templateId,
                    enterpriseEvaluation.getImmutableEvaluateMap());

            companyMapper.deleteCompanyByTemplateId(templateId);
            companyMapper.insertBatch(companies);
        }
        return booleanStringPair;
    }


    private List<Company> readExcel(byte[] buff, boolean isE2007,
                                    Integer templateId, Map<String, Evaluation> evaluationMaps) {
        List<Company> companyLists = new ArrayList<>();
        Map<Integer, String> headMaps = new HashMap<>();
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buff);
            Workbook wb = isE2007 ? new XSSFWorkbook(byteArrayInputStream) : new HSSFWorkbook(byteArrayInputStream);
            Sheet sheet = wb.getSheetAt(0);        //获得第一个表单
            Iterator<Row> rows = sheet.rowIterator();    //获得第一个表单的迭代器
            int RowCount = 0;
            boolean headFlag = false;
            while (rows.hasNext()) {
                Row row = rows.next();    //获得行数据
                headFlag = (RowCount == 0); //第一行为首行
                Iterator<Cell> cells = row.cellIterator();    //获得第一行的迭代器
                int colCount = 0;
                Company company = new Company();
                company.setTemplateId(templateId);
                while (cells.hasNext()) {
                    Cell cell = cells.next();
                    if (headFlag) {
                        headMaps.put(colCount, cell.getStringCellValue());
                    } else if (colCount == 0 && cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                        company.setCompanyName(cell.getStringCellValue());
                    } else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
                        setCompanyProb(cell.getNumericCellValue(), headMaps.get(colCount), company, evaluationMaps);
                    }
                    colCount++;
                }
                RowCount++;
                if (headFlag) {
                    continue;
                }
                companyLists.add(company);

            }
        } catch (IOException ex) {
            logger.error("{}", ex.getMessage());
        }
        return companyLists;
    }

    private Pair<Boolean, String> checkExcel(byte[] buff, boolean isE2007) {
        boolean resultFlag = true;
        String res = null;
        int colNum = 0;
        try {
            ByteArrayInputStream input = new ByteArrayInputStream(buff);
            Workbook wb = isE2007 ? new XSSFWorkbook(input) : new HSSFWorkbook(input);
            Sheet sheet = wb.getSheetAt(0);        //获得第一个表单
            Iterator<Row> rows = sheet.rowIterator();    //获得第一个表单的迭代器
            int RowCount = 0;
            boolean headFlag = false;
            while (resultFlag && rows.hasNext()) {
                Row row = rows.next();  //获得行数据
                headFlag = (RowCount == 0); //第一行为首行
                Iterator<Cell> cells = row.cellIterator();    //获得第一行的迭代器
                int colCount = 0;
                while (resultFlag && cells.hasNext()) {
                    Cell cell = cells.next();
                    if (headFlag) {
                        resultFlag = (cell.getCellType() == HSSFCell.CELL_TYPE_STRING);
                    } else if (colCount == 0) {
                        resultFlag = (cell.getCellType() == HSSFCell.CELL_TYPE_STRING);
                    } else {
                        resultFlag = (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC);
                    }
                    colCount++;
                }
                colNum = RowCount == 0 ? colCount : colNum;
                resultFlag = colNum == colCount;
                RowCount++;
            }
            res = !resultFlag ? Constants.DEFAULT_ERROR : "";
        } catch (IOException ex) {
            res = ex.getMessage();
            logger.error("{}", ex.getMessage());
        }
        return ImmutablePair.of(resultFlag, res);
    }

    private void setCompanyProb(double score, String colName, Company company, Map<String, Evaluation> evaluationMaps) {
        Evaluation evaluation = evaluationMaps.get(colName);
        if (evaluation == null) {
            return;
        }
        double prob = NormUtils.cumulativeProbability(score, evaluation);
        switch (evaluation.getType()) {
            case 1:
                company.setInnovativeInputCapacity(company.getInnovativeInputCapacity() + prob * evaluation.getWeight());
                break;
            case 2:
                company.setInnovationOutputCapacity(company.getInnovationOutputCapacity() + prob * evaluation.getWeight());
                break;
            case 3:
                company.setInnovationPracticalCapacity(company.getInnovationPracticalCapacity() + prob * evaluation.getWeight());
                break;
            case 4:
                company.setInnovationFoundationCondition(company.getInnovationFoundationCondition() + prob * evaluation.getWeight());
                break;
            case 5:
                company.setOtherCapacity(company.getOtherCapacity() + prob * evaluation.getWeight());
                break;
        }
    }
}
